from typing import Union,List,Set

from fastapi import FastAPI,Query,Path,Body,Cookie,Header
from pydantic import BaseModel, Field, HttpUrl,EmailStr
from enum import Enum

from uuid import UUID
from datetime import datetime, time,timedelta

app = FastAPI()


class Item(BaseModel):
    name: str
    price: float
    is_offer: Union[bool, None] = None

class Clq_Class_name(str, Enum):
    Name = 'clq'
    Year = 18
    Id = '431023199509200010'
    student = False

@app.get("/")
def read_root():
    """
        返回 {"Hello": "World"}
    """
    return {"Hello": "World"}

@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
    """
    声明路径参数的类型
    :param item_id: int
    :param q:
    :return:
    """
    return {"item_id": item_id, "q": q}
@app.get("/clq/{clq_str}")
def root(clq_str: Clq_Class_name):
    return {"year": clq_str.Year, "name": clq_str.Name,'status':clq_str.Id}

@app.get("/files/{file_path:path}")
def read_file(file_path: str):
    return {"file_path": "/"+file_path}

@app.get("/adds/")
def add(num1: int=3,num2: int= 8):
    return {"num1 + num2 = ":num1 + num2}



class ItemA(BaseModel):
    name:str
    description: str = None
    price: float
    tax: float = None

class User(BaseModel):
    username: str
    phone: str
    age: int = None

@app.post("/items/")
async def create_item(item: ItemA):
    return item


@app.get("/items/")
def read_items(q:str = Query
    (
 None,
        min_length=3,
        max_length=50,
        title="Query string",
        description="Query string for the items to search in the database that have a good match",
        alias="item-query",
        regex="^fixedquery$",
    )
):
    results = {"items" : 'Big preoject'}
    if q:
        results.update({"q" : q})
    return results

@app.get("/Items/")
async def read_items(q: List[str] = Query(None)):
    query_items = {"q":q}
    return query_items


@app.get("/items6/{item_id}")
async def read_items6(
  q: str = Query(None, alias="item-query"), item_id: int = Path(..., title="The ID of the item to get")
):
    results = {"item_id": item_id}
    if q:
        results.update({"q":q})
    return results

@app.get("/items62/{item_id}")
async def read_items(
*, item_id: int = Path(..., title="The ID of the item to get"),q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

@app.get("/items63/{item_id}")
async def read_items(
*, item_id: float = Path(..., title="The ID of the item to get",gt=3.5,lt=100.95),q: str):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

@app.put("/items7/{item_id}")
async def update_item7(
        *,
        item_id: int = Path(...,title="The ID of the item to get",gt=3,lt=100),
        q:str = None,
        item: ItemA = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if item:
        results.update({"item": item})
    return results

@app.put("/items72/{item_id}")
async def update_item72(
        *,
        item_id: int = Path(...,title="The ID of the item to get",gt=3,lt=100),

        item: ItemA = None,
        user: User = None,
):
    results = {"item_id": item_id}
    if User:
        results.update({"user": user})
    if item:
        results.update({"item": item})
    return results

@app.put("/items73/{item_id}")
async def update_item73(
        *,
        item_id: int = Path(...,title="The ID of the item to get",gt=3,lt=100),
        item: ItemA = None,
        user: User = None,
        importance: int = Body(...)
):
    results = {"item_id": item_id,"item":item,"user":user,"importance":importance}
    return results


@app.put("/items74/{item_id}")
async def update_item74(
        *,
        item_id: int,
        item: ItemA = Body(...,embed=True),
):
    results = {"item_id": item_id, "item":item}
    return results



class Item80(BaseModel):
    name: str
    description: str = Field(..., title="The description of the item", max_length=5)
    price: float = Field(...,gt=1, description="The price must be greater than 0")
    tax: float = None
 

@app.put("/items80/{item_id}")
async def update_item80(
    *,
    item_id: int = Path(..., title="The ID of the item to get",gt=3,lt=100),
    item: Item80 = Body(...,embed=True)
):
    results = {"item_id": item_id, "item":item}
    return results

@app.put("/items82/{item_id}")
async def update_item82(
    *,
    item_id: int = Path(..., title="The ID of the item to get",gt=3,lt=100),
    itme: ItemA = Body(...,
                        example={ "name": "Foo", "description": "A very nice Item", "price": 35.4, "tax": 3.2, },)
):
    results = {"item_id": item_id, "item":itme}
    return results
# example - 示例格式   访问 http://127.0.0.1:8000/docs 可以查看Body 中需要传入Json格式的示例



class Image90(BaseModel):
    url: HttpUrl
    name: str

class Item90(BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None
    tags: Set[str] = []  # 表示属性值的类型为元组，元组中元素的类型为字符串
    images: List[Image90] = None

@app.put("/items90/{item_id}")
async def update_item90(*,item_id: int, item: Item90):
    results = {"item_id": item_id, "item":item}
    return results


class Offer(BaseModel):
    name: str
    description: str = None
    price: float
    items: List[Item90]


@app.put("/offers/{item_id}")
async def create_offer(*,offer: Offer):
    return offer


@app.put("/items100/{item_id}")
async def read_items100(
        item_id: UUID,     #UUID: 通用唯一识别码，通常是一个128位的数字，表示为32个十六进制数字： 例如 550e8400-e29b-41d4-a716-446655440000
        start_datetime: datetime = Body(None),
        end_datetime: datetime = Body(None),
        repeat_at: time = Body(None),
        process_after: timedelta = Body(None),
):
    start_process = start_datetime + process_after
    duration = end_datetime - start_process

    return{
        "item_id": item_id,
        "start_datetime": start_datetime,
        "end_datetime": end_datetime,
        "repeat": repeat_at,
        "process_after": process_after,
        "start_process": start_process,
        "duration": duration,
    }

@app.get("/items110/{item_id}")
async def read_items110(
    *,
    item_id: int,
    ads_id: str = Cookie(default="No ID", title="Advertisement ID", description="The ID for the advertisement"),
    token: str = Cookie(default="No token")
):
    return {"item_id":item_id,"ads_id": ads_id,"token":token}


@app.get("/items120/{item_id}")
async def read_items120(
    *,
    item_id: int,
    user_agent: str = Header("Mozilla/5.0",title="User-Agent"),
):
    return {"item_id":item_id,"user_agent":user_agent}



class UserIn(BaseModel):
    username: str
    password: str
    email: EmailStr
    full_name: str = None

class UserOut(BaseModel):
    username: str
    email: EmailStr
    full_name: str = None

@app.post("/user/",response_model=UserOut)
async def create_user(*, user: UserIn):
    return user










